package com.example.klinedemo.play

import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.media.MediaCodec
import android.media.MediaFormat
import android.view.Surface
import java.io.ByteArrayOutputStream
import java.io.DataInputStream
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.lang.Exception

class H264Player// 不支持的格式 // video 代表视频  audio 代表音频
// video 斜杠后面  是 视频的格式 比如h264 h265
    (
    var path: File,// 解码器
    val surface: Surface
) : Runnable {

    var mediaCodec: MediaCodec? = null// 显示数据源的view

    init {
        try {
            // video 代表视频  audio 代表音频
            // video 斜杠后面  是 视频的格式 比如h264 h265
            mediaCodec = MediaCodec.createDecoderByType("video/avc")
            val mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480)
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 15)
            mediaCodec?.configure(mediaFormat, surface, null, 0)


        } catch (e: IOException) {
            e.printStackTrace()
            // 不支持硬解码的格式
        }


    }


    fun play() {
        mediaCodec?.start()
        Thread(this).start()
    }

    override fun run() {
        try {
            decodeH264()
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    private fun decodeH264() {
        val byte = getBytes(path)
        // 获取到输入队列 所有的节点
        // 获取一个可以传输数据的节点，他的参数是等待时间
        val inputBufferIndex = mediaCodec?.dequeueInputBuffer(10000)?:-1
        var startIndex = 0;
        val bufferInfo = MediaCodec.BufferInfo()
        while (true) {
            if (inputBufferIndex == -1) return

            val nexStart = findByFrame(byte, startIndex + 2, byte.size)
            if (inputBufferIndex >= 0) {
                // 拿到空余的节点
                val byteBuffer = mediaCodec?.getInputBuffer(inputBufferIndex)
                // 按照帧的大小来进行丢数据
                val length = nexStart - startIndex
                byteBuffer?.put(byte, startIndex, length)
                // 将数据传递给dsp解码器
                // 只需要告诉dsp，我用的是第几个容器
                mediaCodec?.queueInputBuffer(inputBufferIndex, 0, length, 0, 0)
            }
            // 返回值是一个索引，如果有索引 就证明数据处理完毕
            val outIndex = mediaCodec?.dequeueOutputBuffer(bufferInfo, 10000)?.let { outIndex ->
                if (outIndex >= 0) {
                    // 容器利用完毕了，需要释放容器
                    // 第二个参数传递true 直接会渲染到 surface中
                    mediaCodec?.releaseOutputBuffer(outIndex, true)

                }
            }
        }

    }

    private fun findByFrame(byte: ByteArray, start: Int, totalStart: Int): Int {
        for (i in start..totalStart - 4) {
            if ((byte[i] == 0x00.toByte() && byte[i + 1] == 0x00.toByte()
                        && byte[i + 2] == 0x00.toByte() && byte[i + 3] == 0x01.toByte()) ||
                (byte[i] == 0x00.toByte() && byte[i + 1] == 0x00.toByte()
                        && byte[i + 2] == 0x01.toByte())
            ) {
                return i
            }
        }
        return -1
    }

    private fun getBytes(path: File): ByteArray {
        DataInputStream(FileInputStream(path)).use { inputStream ->
            val bos = ByteArrayOutputStream()
            val buffer = ByteArray(1024) // 创建缓冲区

            var bytesRead: Int
            while (inputStream.read().also { bytesRead = it } != -1) {
                bos.write(buffer, 0, bytesRead) // 写入有效读取部分
            }

            return bos.toByteArray() // 返回完整字节数组
        }
    }


}